package main

import (
	"fmt"
	"log"
	"net"
	"strings"
	"time"
)

type Client struct {
	C    chan string
	Name string
	Addr string
}

//创建全局map，存储在线用户
var onlineMap map[string]Client

//创建全局channel，传递用户信息
var message = make(chan string)

func WriteMsgToClient(clnt Client, conn net.Conn) {
	for msg := range clnt.C {
		conn.Write([]byte(msg + "\n"))
	}
}

func MakeMsg(clnt Client, msg string) string {
	buf := "[" + clnt.Addr + "]" + clnt.Name + ":" + msg
	return buf
}

func HandlerConnect(conn net.Conn) {
	defer conn.Close()
	netAddr := conn.RemoteAddr().String()
	clnt := Client{make(chan string), netAddr, netAddr}
	//添加到map
	onlineMap[netAddr] = clnt
	//创建channel检查用户是否活跃
	hasData := make(chan bool)
	//创建专门给当前用户发送消息的goroutine
	go WriteMsgToClient(clnt, conn)
	//发送上线消息到全局channel
	message <- MakeMsg(clnt, "login")
	//创建一个channel,用来判断退出状态
	isQuit := make(chan bool)
	go func() {
		buf := make([]byte, 4096)
		for {
			n, err := conn.Read(buf)
			if n == 0 {
				isQuit <- true
				fmt.Printf("检测到客户端:%s退出\n", clnt.Name)
				return
			}
			if err != nil {
				log.Println("conn.Read出错", err)
				return
			}
			msg := string(buf[:n])
			if len(msg) == 3 && msg == "who" {
				conn.Write([]byte("online user list:\n"))
				for _, user := range onlineMap {
					userInfo := user.Addr + ":" + user.Name + "\n"
					conn.Write([]byte(userInfo))
				}
			} else if len(msg) > 7 && msg[:6] == "rename" {
				newName := msg[7:]
				clnt.Name = newName
				onlineMap[netAddr] = clnt
				conn.Write([]byte("rename successfully\n"))
			} else if len(msg) > 2 && msg[:2] == "To" {
				tmp := strings.Split(msg, ":")
				name := tmp[0][3:]
				for _, j := range onlineMap {
					if j.Name == name {
						j.C <- tmp[1]
					}
				}
			} else {
				message <- MakeMsg(clnt, msg)
			}
			hasData <- true
		}
	}()
	for {
		select {
		case <-isQuit:
			delete(onlineMap, netAddr)
			message <- MakeMsg(clnt, "logout")
			return
		case <-hasData:
			//重置计时器
		case <-time.After(time.Second * 60):
			delete(onlineMap, netAddr)
			message <- MakeMsg(clnt, "logout")
			return
		}
	}
}
func Manager() {
	//初始化map和message
	onlineMap = make(map[string]Client)

	for {
		//循环监听message
		msg := <-message
		//循环发送消息给在线用户
		for _, clnt := range onlineMap {
			clnt.C <- msg
		}
	}

}
func main() {
	//创建监听套接字
	listener, err := net.Listen("tcp", "127.0.0.1:8000")
	if err != nil {
		log.Println("Listen err", err)
		return
	}
	defer listener.Close()

	go Manager()
	//循环监听客户端连接请求
	for {
		conn, err := listener.Accept()
		if err != nil {
			log.Println("Accept err", err)
			return
		}
		go HandlerConnect(conn)
	}
}
